

import java.io.IOException;


public class runEnvironment {

	/**
	 * @param args
	 * @throws IOException 
	 */
	
	public static void main(String[] args) throws IOException {
		// getting parameters from args - in a list : 
		//[0]Trackname
		//[1]Episodes, 
		//[2]Learning Speed
		//[3]Number of hidden neurons
		//[4]Switch (t=show visual when done; r=random agent,s=save nn with filename,l=load from filename,m=load&show, rest is just train)
		//[6]Filename used for saving/loading

		String[] argslist = {"circularcomplex.txt","5000","0.0001","50","s","filename","1", "1"};

		//This loop avoids, errors if there is no parameter given - by mixing args + argslist
		for(int i=0; i<args.length; i++){
			argslist[i]=args[i];
		}
		
		//Parse the strings to useable values
		String trackname = argslist[0];
		int episodes = Integer.parseInt(argslist[1]);
		double learnNetSpeed = Double.parseDouble(argslist[2]);
		int hiddenNeurons = Integer.parseInt(argslist[3]);
		String switchkey = argslist[4];
		String saveName = argslist[5];
		double discount = Double.parseDouble(argslist[6]);
		double lambda = Double.parseDouble(argslist[7]);
		
		
		//Number of cars isn't in the parameters, since we didn't get around to testing it.
		//Can still be used fine. Maximum number depends on how many starting positions there are on the track.
		//If you want to visualize the output, the maximum is 4.
		int numberofcars = 1;  		
		
		//Maximum speed can also be changed if wanted.
		int maxspeed = 3;
		
		//Some nice printing
		System.out.println("Trackname			: "+trackname);
    	System.out.println("number of episodes  : "+episodes);
    	System.out.println("NN Learningspeed    : "+learnNetSpeed);
    	System.out.println("Hidden Neurons 	    : "+hiddenNeurons);
    	System.out.println("Maximum Speed       : "+maxspeed);
    	if (switchkey.equals("l") || switchkey.equals("m") || switchkey.equals("s")) {
    		System.out.println("Switch: " + switchkey + "	    : "+saveName);
    	}
    	if(discount<1) System.out.println("Discount			: "+discount); 
    	if(lambda<1) System.out.println("Lambda				: "+lambda); 
		

    	//Creates the environment with the given parameters
    	Environment env = new Environment(trackname,numberofcars,false,maxspeed,learnNetSpeed, hiddenNeurons);
		
    	//And let the training commence.
    	trainRun(env,episodes, argslist);
	}
	
	//Runs the training
	public static void trainRun(Environment env, int trainingnumber, String[] argslist) throws IOException {
		
		//During training we don't want to see it
		env.setVisible(false);
		
		//At the beginning the exploration is 1.
		double exploration = 1;
		double discount = Double.parseDouble(argslist[6]);
		double lambda = Double.parseDouble(argslist[7]);
		
		//We want to decrease each step until it's 0.01 at the end.
		double decrease_explore = 0.99 / trainingnumber;
		
	    //If the switch is set to r, set random agents
		if (argslist[4].equals("r")) env.setRandomAgent();
		if(discount<1) env.setDiscount(discount);
		if(lambda<1) env.setLambda(lambda);
		
		//If the switch is l or m, load agents from file
		//Set exploration to 0, we don't want it to explore again.
		if (argslist[4].equals("l") || argslist[4].equals("m")) {
			try {
				env.restoreNN(argslist[5]);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			env.setExploration(0.0);
			for(int i=0; i < trainingnumber; i++)
		    {
                System.out.print(i + "-" + exploration + "-");
                int result = env.run();
                System.out.println(result);
                env.reset();
		    }
			
		}
		
		
		//Normal training. As stated before, exploration is slowly decreased until 0.01
		else {
			for(int i=0; i < trainingnumber; i++)
			{
				env.setExploration(exploration);
				exploration -= decrease_explore;
				System.out.print(i + "-" + exploration + "-");
				int result = env.run();
				System.out.println(result);
				env.reset();
			}

		}
		
		//If the switch is t or m, show a run visually.
		if (argslist[4].equals("t") || argslist[4].equals("m"))

		{
			System.out.println("Press any key to continue");
			System.in.read();
			env.setVisible(true);
			env.run();
		}
		
		//If the switch is s, save the agents.
		if (argslist[4].equals("s"))

		{
			env.saveNN(argslist[5]);
			System.out.println("Saved to " + argslist[6]);
		}
	}

}
